package com.fzy.core.webwork;

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;

import com.fzy.core.spring.SpringContextHolder;
import com.opensymphony.util.TextUtils;
import com.opensymphony.xwork.ActionContext;
import com.opensymphony.xwork.ActionInvocation;
import com.opensymphony.xwork.ActionProxy;
import com.opensymphony.xwork.ActionProxyFactory;
import com.opensymphony.xwork.XWorkMessages;
import com.opensymphony.xwork.config.ConfigurationException;
import com.opensymphony.xwork.config.ConfigurationManager;
import com.opensymphony.xwork.config.entities.ActionConfig;
import com.opensymphony.xwork.config.entities.PackageConfig;
import com.opensymphony.xwork.config.providers.InterceptorBuilder;
import com.opensymphony.xwork.config.providers.XmlConfigurationProvider;
import com.opensymphony.xwork.util.LocalizedTextUtil;

public class MyActionProxy implements ActionProxy, Serializable {
	

	/**
	 * 
	 */
	private static final long serialVersionUID = 5883392514985786819L;

	private static final Logger LOG = LoggerFactory.getLogger(MyActionProxy.class);

    protected ActionConfig config;
    protected ActionInvocation invocation;
    protected Map extraContext;
    protected String actionName;
    protected String namespace;
    protected String method;
    protected boolean executeResult;
    protected boolean cleanupContext;

    /**
     * This constructor is private so the builder methods (create*) should be used to create an DefaultActionProxy.
     * <p/>
     * The reason for the builder methods is so that you can use a subclass to create your own DefaultActionProxy instance
     * (like a RMIActionProxy).
     */
    protected MyActionProxy(String namespace, String actionName, Map extraContext, boolean executeResult, boolean cleanupContext) throws Exception {
        this.cleanupContext = cleanupContext;
        if (LOG.isDebugEnabled()) {
            LOG.debug("Creating an DefaultActionProxy for namespace " + namespace + " and action name " + actionName);
        }

        this.actionName = actionName;
        this.namespace = namespace;
        this.executeResult = executeResult;
        this.extraContext = extraContext;

        // add by zhx
        ConfigurationManager.addConfigurationProvider(new XmlConfigurationProvider("webwork-fzy.xml"));
        addXworkXml();
        config = ConfigurationManager.getConfiguration().getRuntimeConfiguration().getActionConfig(namespace, actionName);
        
        if(config == null && namespace.startsWith("/mapping/")){
        	PackageConfig p = ConfigurationManager.getConfiguration().getPackageConfig("default");
        	List i = InterceptorBuilder.constructInterceptorReference(p, "commonStack", new LinkedHashMap());
        	String a = StringUtils.capitalize(actionName.toLowerCase());
        	String actionClassName = "common"+a+"Action";
        	config = new ActionConfig(null, actionClassName, new TreeMap(), new TreeMap(), i, new ArrayList(), new ArrayList(), namespace);
        }
//        if(config == null){
////        	Map classMappings = (Map) invocation.getInvocationContext().getApplication().get(MyContextLoaderServlet.CLASS_MAPPINGS);
//        	Map application = (Map)extraContext.get(ActionContext.APPLICATION);
//        	Map classMappings = (Map) application.get(MyContextLoaderServlet.CLASS_MAPPINGS);
//        	for (Iterator iterator = classMappings.entrySet().iterator(); iterator.hasNext();) {
//				Map.Entry entry = (Map.Entry) iterator.next();
//				MappingClass c = (MappingClass)entry.getValue();
//				String className = c.getName();
//				String className2 = StringUtils.uncapitalize(className.substring(className.lastIndexOf(".") + 1));
//				String n = c.getNamespace();
//				if(!n.startsWith("/")) n = "/" + n;
//				if(!n.endsWith("/")) n = n + "/";
//				String namespace2 = n + className2;
//				if(namespace2.trim().equals(namespace)){
//		        	PackageConfig p = ConfigurationManager.getConfiguration().getPackageConfig("default");
//		        	List i = InterceptorBuilder.constructInterceptorReference(p, "commonStack", new LinkedHashMap());
//		        	String actionClassName = actionName + "Action";
//		        	config = new ActionConfig(null, actionClassName, new TreeMap(), new TreeMap(), i, new ArrayList(), new ArrayList(), namespace2);
//		        	this.extraContext.put("_c", c);
//				}
//			}
//        }

        if (config == null) {
            String message;

            if ((namespace != null) && (namespace.trim().length() > 0)) {
                message = LocalizedTextUtil.findDefaultText(XWorkMessages.MISSING_PACKAGE_ACTION_EXCEPTION, Locale.getDefault(), new String[]{
                        namespace, actionName
                });
            } else {
                message = LocalizedTextUtil.findDefaultText(XWorkMessages.MISSING_ACTION_EXCEPTION, Locale.getDefault(), new String[]{
                        actionName
                });
            }

            throw new ConfigurationException(message);
        }

        prepare();
    }
    
 // add by zhx
    private void addXworkXml(){
    	String webworkXmlPattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + "webwork/xwork-*.xml";
    	ResourceLoader resourceLoader = SpringContextHolder.getApplicationContext();
    	ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(resourceLoader);
        try {
			Resource[] rules = resolver.getResources(webworkXmlPattern);
			for (int i = 0; i < rules.length; i++) {
				Resource r = rules[i];
				ConfigurationManager.addConfigurationProvider(new XmlConfigurationProvider("webwork/" + r.getFilename()));
			}
		} catch (IOException e) {
			LOG.error(e.getMessage(), e);
		}
    }

    public Object getAction() {
        return invocation.getAction();
    }

    public String getActionName() {
        return actionName;
    }

    public ActionConfig getConfig() {
        return config;
    }

    public void setExecuteResult(boolean executeResult) {
        this.executeResult = executeResult;
    }

    public boolean getExecuteResult() {
        return executeResult;
    }

    public ActionInvocation getInvocation() {
        return invocation;
    }

    public String getNamespace() {
        return namespace;
    }

    public String execute() throws Exception {
        ActionContext nestedContext = ActionContext.getContext();
        ActionContext.setContext(invocation.getInvocationContext());

        String retCode = null;

        try {
            retCode = invocation.invoke();
        } finally {
            if (cleanupContext) {
                ActionContext.setContext(nestedContext);
            }
        }

        return retCode;
    }


    public String getMethod() {
        return method;
    }

    public void setMethod(String method) {
        this.method = method;
        resolveMethod();
    }

    private void resolveMethod() {
        // if the method is set to null, use the one from the configuration
        // if the one from the configuration is also null, use "execute"
        if (!TextUtils.stringSet(this.method)) {
            this.method = config.getMethodName();
            if (!TextUtils.stringSet(this.method)) {
                this.method = "execute";
            }
        }
    }

    protected void prepare() throws Exception {
        invocation = ActionProxyFactory.getFactory().createActionInvocation(this, extraContext);
        resolveMethod();
    }
}
